// 该文件与tx_p1联合实现点对点聊天 使用io多路复用的方式

#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <error.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define MAXLINE 1024
//select返回就绪的io事件的个数，超时则返回0 失败返回-1 并设置errno

int main(int argc, char* argv[])
{
    //先在外面创建有名管道 FIFO
    //一切皆文件
    //打开管道 open的返回值为文件描述符
    int fd1 = open("p1", O_RDONLY);
    if(fd1 == -1)
    {
        //返回-1 打开文件失败
        error(1, errno, "open f1 fail");
    }
    int fd2 = open("p2", O_WRONLY);
    if(fd2 == -1)
    {
        error(1, errno, "open f2 fail");
    }

    //1.设置感兴趣的文件描述符也就是要监听的文件描述符
    fd_set mainfds;
    //先清空fdset所指向的集合
    FD_ZERO(&mainfds);

    //将文件描述符fd添加到fdset指向的集合中
    FD_SET(STDIN_FILENO, &mainfds);
    int maxfd = STDIN_FILENO;
    //p2 检测 管道p1

    printf("开始聊天：\n");
    FD_SET(fd1, &mainfds);
    if(fd1 > maxfd)
    {
        maxfd = fd1;
    }

    //定义数组，用来存储输出输入信息
    char sndline[MAXLINE];
    char recline[MAXLINE];

    while(1)
    {
        //因为select 参数为传入传出参数，会改变参数的值，所以复制一份每一次都是监测值
        //这也是fd_set 设计的妙处 结构体的赋值就是结构体的复制，这是不使用数组的原因
        fd_set readfd = mainfds;
        //因为这是用来处理阻塞点的所以，只要监听read就可以了
        int nfd = select(maxfd+1, &readfd, NULL, NULL, NULL);
        switch (nfd)
        {
            case -1:
                error(1, errno, "select");
            case 0:
                //超时
                printf("time out\n");
                continue;
            default:
                //STDIN就绪
                if(FD_ISSET(STDIN_FILENO, &readfd))
                {
                    fgets(sndline, MAXLINE, stdin);
                    write(fd2, sndline, strlen(sndline)+1);
                }
                //fd1就绪
                if(FD_ISSET(fd1, &readfd))
                {
                    int num = read(fd1, recline, MAXLINE);
                    if(num == 0)
                    {
                        //没有读取到数据，说明对面的通道关闭
                        goto end;
                    }else if(num == -1)
                    {
                        error(1, errno, "read");
                    }
                    printf("For 1:%s", recline);
                }
        }
    }
    
end:
    close(fd1);
    close(fd2);
    return 0;
}